//
//  FBMediaShareCommunity.m
//  MediaShareBB
//
//  Created by Artak Gevorgyan on 5/23/13.
//  Copyright (c) 2013 InnoriseEntertainment. All rights reserved.
//

#import "AppDelegate.h"
#import "FBMediaShareCommunity.h"
#import "FBMediaShareCommunityEntity.h"
#import "MediaShareBBUtilityMethods.h"
#import "MediaShareData.h"

#import <FacebookSDK/FBSessionTokenCachingStrategy.h>
#import <FacebookSDK/FBSession.h>
#import <FacebookSDK/FBAccessTokenData.h>
#import <FacebookSDK/FBWebDialogs.h>
#import <Social/Social.h>
#import <Accounts/Accounts.h>


@interface FBMediaShareCommunity()
{
	FBAccessTokenData* _accessToken;
	FBMediaShareCommunityEntity* _selfEntity;
	FBFriendPickerViewController* _friendPickerController;
	MediaShareData* _sharedMediaData;
	ACAccountStore* _accountStore;
	ACAccount* _facebookAccount;
	NSString* _appId;
    BOOL _loginWithAnotherUser;
}

@end

@implementation FBMediaShareCommunity

-(id) init {
	self = [super init];
	if (self) {
		super.name = @"Facebook";
		super.communityType = MEDIA_SHARE_COMMUNITY_FACEBOOK;
		super.supportedMediaTypes = [[NSArray alloc] initWithObjects:
										[NSNumber numberWithInt:IMAGE_MEDIA_TYPE],
										[NSNumber numberWithInt:VIDEO_MEDIA_TYPE], nil];
	}
	return self;
}

#pragma mark - Superclass methods

// Superclass method
-(NSString*) description {
	NSString* d = @"Facebook description";
	return d;
}

// Superclass method
-(void) configureWithCredentials:(NSDictionary*) credentials {
	_appId = [credentials valueForKey:@"facebookAppId"];
}

// Superclass method
-(void) login {
	if ([self canProceedRequestToShareWithNativeDialog]) {
       [self setFacbookAccount];
        self.isNativeMode = YES;
        _loginWithAnotherUser = NO;
		if ([MediaShareBBUtilityMethods isObject:super.delegate
							  respondsToSelector:@selector(loginSuccess)]) {
			[super.delegate loginSuccess];
		}
	} else {
        self.isNativeMode = NO;
		[self openSessionWithAllowLoginUI:YES];
	}
}

//Superclass method
-(void) loginWithAnotherUser {
        [FBSession.activeSession closeAndClearTokenInformation];
        [FBSession.activeSession close];
        [FBSession setActiveSession:nil];
        _loginWithAnotherUser = YES;
        [self openSessionWithAllowLoginUI:YES];
}

//Superclass method
-(NSString*) getUserName {
    if ([self canProceedRequestToShareWithNativeDialog] && !_loginWithAnotherUser) {
        return  _facebookAccount.username;
    } else {
        return [NSString stringWithFormat:@"%@ %@", _selfEntity.firstName, _selfEntity.lastName];
    }
}

//Superclass method
-(NSString*) sharedMediaLink {
    return @"";
}

// Superclass method
-(void) shareMedia:(MediaShareData*) data {
	if ([super isValidMediaType:data.mediaType]) {
		_sharedMediaData = data;
		[super.delegate willSharingMedia:_sharedMediaData
								 through:self];
		[self performPost];
	} else {
		NSLog(@"%s: Unsupported media type:%d", __PRETTY_FUNCTION__, data.mediaType);
	}
}

-(void) showFriendsPickerOnView:(UIViewController*) vc {
	_friendPickerController = [[FBFriendPickerViewController alloc] init];
	_friendPickerController.title = @"Pick Friends";
	_friendPickerController.delegate = self;
	[_friendPickerController loadData];
	[_friendPickerController clearSelection];
	_friendPickerController.doneButton = nil;
	_friendPickerController.cancelButton = nil;
//	[vc.view addSubview:_friendPickerController.view];
//	[_friendPickerController presentModallyFromViewController:vc
//													 animated:YES
//													  handler:nil];
}

#pragma mark - Public methods

-(void) fetchFriends {
	[[FBRequest requestForMyFriends] startWithCompletionHandler:
	 ^(FBRequestConnection *connection, NSDictionary<FBGraphObject> *users, NSError *error) {
		 if (!error) {
			 NSMutableArray* friends = [users objectForKey:@"data"];
			 [self fetchEntitiesFromCollection:friends selectionMode:NO];
			 if (super.entities.count != 0 &&
				 [MediaShareBBUtilityMethods isObject:super.delegate
								   respondsToSelector:@selector(entitiesFetchedForCommunity:)]) {
				 [super.delegate entitiesFetchedForCommunity:self];
			 }
		 } else {
//			 if ([super.delegate respondsToSelector:@selector(loginFailedWithError:)]) {
//				 [super.delegate loginFailedWithError:error];
//			 }
			 NSLog(@"%s: Friends fetching failed with error: %@", __PRETTY_FUNCTION__, error);
		 }
	 }];
}

#pragma mark - FBViewControllerDelegate methods

-(void) facebookViewControllerDoneWasPressed:(id) sender {
	[self fetchEntitiesFromCollection:_friendPickerController.selection
						selectionMode:YES];
	if (super.selectedEntities.count != 0 &&
		[MediaShareBBUtilityMethods isObject:super.delegate
						  respondsToSelector:@selector(entitiesSelectedForCommunity:)]) {
		[super.delegate entitiesSelectedForCommunity:self];
	}
//	[super.delegate communityViewWillClose];
}

-(void) facebookViewControllerCancelWasPressed:(id) sender {
	[super.delegate communityViewWillClose];
}

#pragma mark - Private methods

-(BOOL) openSessionWithAllowLoginUI:(BOOL) allowLoginUI {
	NSArray* publishPermissions = [[NSArray alloc] initWithObjects:
								   @"offline_access",
								   @"read_stream",
								   @"read_friendlists",
								   @"xmpp_login",
								   @"publish_actions",
								   @"manage_notifications",
								   @"video_upload",
								   nil];
	[FBSession setActiveSession:[[FBSession alloc] initWithPermissions:publishPermissions]];
	[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView
							  completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
			[self sessionStateChanged:session state:state error:error];
	}];
	return YES;
}

-(void) sessionStateChanged:(FBSession *)session
                      state:(FBSessionState)state
                      error:(NSError *)error {
    switch (state) {
        case FBSessionStateOpen: {
            FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];
            [cacheDescriptor prefetchAndCacheForSession:session];
			[self requestSelfUserData];
			break;
        } case FBSessionStateClosed: {
			break;
		} case FBSessionStateClosedLoginFailed: {
            [FBSession.activeSession closeAndClearTokenInformation];
			[super.delegate loginCanceled];
            break;
		} default:
            break;
    }
    if (error) {
		NSLog(@"%s: FB sessionStateChanged. Error:%@", __PRETTY_FUNCTION__, error);
    }
}


-(void) updateAccessToken {
//    _accessToken = [[FBSession activeSession] accessTokenData];
}

-(void) fetchEntitiesFromCollection:(NSArray*) collection
					  selectionMode:(BOOL) selectionMode {
    for (id<FBGraphUser> user in collection) {
		FBMediaShareCommunityEntity* e = [self constructEntityWithUserData:user];
		if (selectionMode) {
			[super.selectedEntities addObject:e];
		} else {
			[super.entities addObject:e];
		}
    }
}

-(FBMediaShareCommunityEntity*) constructEntityWithUserData:(id<FBGraphUser>) user {
	NSLog(@"%s: user data __________________", __PRETTY_FUNCTION__);
	FBMediaShareCommunityEntity* e = [[FBMediaShareCommunityEntity alloc]
									  initWithEntityId:user.id];
	e.firstName = [user objectForKey:@"first_name"];
	e.lastName = [user objectForKey:@"last_name"];
	return e;
}

-(void) requestSelfUserData {
	[[FBRequest requestForMe] startWithCompletionHandler:
	 ^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
		 if (!error) {
			 _selfEntity = [self constructEntityWithUserData:user];
			 _selfEntity.isMyEntity = YES;
			 [super.entities addObject:_selfEntity];
			 [self updateAccessToken];
			 if ([MediaShareBBUtilityMethods isObject:super.delegate
								   respondsToSelector:@selector(loginSuccess)]) {
				 [super.delegate loginSuccess];
				 [FBFriendPickerViewController class];
			 }
		 } else {
			 if ([MediaShareBBUtilityMethods isObject:super.delegate
								   respondsToSelector:@selector(loginFailedWithError:)]) {
				 [super.delegate loginFailedWithError:error];
			 }
		 }
	 }];
}

-(void) performPost {
	if ([self canProceedRequestToShareWithNativeDialog] && !_loginWithAnotherUser) {
		[self performNativeFBPost];
	} else {
		if ([MediaShareBBUtilityMethods isObject:super.delegate
							  respondsToSelector:@selector(willSharingMedia:through:)]) {
			[super.delegate willSharingMedia:_sharedMediaData through:self];
		}
		[self performCustomFBPost];
	}
}

-(void) performCustomFBPost {
	if (_sharedMediaData.mediaType == VIDEO_MEDIA_TYPE) {
		[self uploadVideoInFBCustomMode];
	} else if (_sharedMediaData.mediaType == IMAGE_MEDIA_TYPE) {
		[self uploadImageInFBCustomMode];
	}
}

-(void) performNativeFBPost {
	if (_sharedMediaData.mediaType == IMAGE_MEDIA_TYPE) {
		[self uploadImageInFBNativeMode];
	} else if (_sharedMediaData.mediaType == VIDEO_MEDIA_TYPE) {
		[self uploadVideoInFBNativeMode];
	}
}

-(BOOL) canProceedRequestToShareWithNativeDialog {
    BOOL result = NO;
	result = [SLComposeViewController
				  isAvailableForServiceType:SLServiceTypeFacebook];
	return result;
}

-(void) setImages:(NSArray*) images toFBViewController:(id) fbVC {
	if (images != nil ) {
		for (UIImage* image in images) {
			[fbVC addImage:image];
		}
	}
}

-(void) setCompletionHandlersToFBViewController:(SLComposeViewController*) fbVC {
	[fbVC setCompletionHandler:^(SLComposeViewControllerResult result) {

		switch (result) {
			case SLComposeViewControllerResultDone: {
				if ([MediaShareBBUtilityMethods isObject:super.delegate
									  respondsToSelector:@selector(didFinishSharingMedia:through:)]) {
					[super.delegate didFinishSharingMedia:_sharedMediaData
												  through:self];
				}
				break;
			} case SLComposeViewControllerResultCancelled: {
				[super.delegate communityViewWillClose];
				break;
			}
		}
	}];
}

-(void) presentViewController:(UIViewController*) vc {
    if ([MediaShareBBUtilityMethods isObject:super.delegate
						  respondsToSelector:@selector(targetViewController)]) {
		AppDelegate* app = [UIApplication sharedApplication].delegate;
		UIViewController* controller = app.window.rootViewController;
//        UIViewController* controller = [super.delegate targetViewController];
//        if (IPAD) {
//			_login.modalPresentationStyle = UIModalPresentationFormSheet;
//        }
		if ( [controller respondsToSelector:
			  @selector(presentViewController:animated:completion:)] ) {
			[controller presentViewController:vc animated:YES completion:nil];
		} else if ( [controller respondsToSelector:
					 @selector(presentModalViewController:animated:)] ) {
			[controller presentViewController:vc animated:YES completion:nil];
		}
    }
}

-(void) uploadImageInFBCustomMode {
    UIImage *image = [MediaShareBBUtilityMethods imageFromData:_sharedMediaData.data];
    NSDictionary *parameters = @{
                                  @"name": _sharedMediaData.fileName,
                                  @"picture": image
                                  };
    FBRequest *request = [FBRequest requestWithGraphPath:@"me/photos"
                                              parameters:parameters
                                              HTTPMethod:@"POST"];
    FBRequestConnection *connection = [[FBRequestConnection alloc] init];
    [connection addRequest:request
         completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
             
             if (!error) {
                 [super.delegate didFinishSharingMedia:_sharedMediaData through:self];
             } else {
                 NSLog(@"%s: Error %@", __FUNCTION__, error.localizedDescription);
                 [super.delegate didFailedSharingMedia:_sharedMediaData through:self
                                             withError:error];
             }             
         }];
    [connection start];
}

-(void) uploadVideoInFBCustomMode {
	if (!FBSession.activeSession.isOpen) {
		NSLog(@"Facebook active session can not be closed");
	}
	NSString* filePath = _sharedMediaData.path;
	NSURL *pathURL = [[NSURL alloc] initFileURLWithPath:filePath isDirectory:NO];
	NSData *videoData = _sharedMediaData.data;
	NSDictionary *videoObject = @{
									@"title": @"",
									@"description": _sharedMediaData.fileName,
									[pathURL absoluteString]: videoData
								};
	FBRequest *uploadRequest = [FBRequest requestWithGraphPath:@"me/videos"
													parameters:videoObject
													HTTPMethod:@"POST"];
	[uploadRequest startWithCompletionHandler:^(FBRequestConnection *connection,
												id result, NSError *error) {
		if (!error) {
			NSLog(@"%s: Successfully uploaded video", __PRETTY_FUNCTION__);
			[super.delegate didFinishSharingMedia:_sharedMediaData
										  through:self];
		} else {
			NSLog(@"%s: Video upload failed with error: %@", __PRETTY_FUNCTION__, error);
			[super.delegate didFailedSharingMedia:_sharedMediaData through:self
										withError:error];
		}
	}];
}

-(void) uploadImageInFBNativeMode {
	NSString* text = _sharedMediaData.fileName;
	NSArray* images = [NSArray arrayWithObject:[MediaShareBBUtilityMethods
													imageFromData:_sharedMediaData.data]];
	NSString* url = nil;
	if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook] ) {
		SLComposeViewController* fbController = [SLComposeViewController
												 composeViewControllerForServiceType:SLServiceTypeFacebook];
		[fbController setInitialText:text];
		[self setImages:images toFBViewController:fbController];
		if (url != nil) {
			[fbController addURL:[NSURL URLWithString:url]];
		}
		[self setCompletionHandlersToFBViewController:fbController];
		[self presentViewController:fbController];
	}
}

-(void) setFacbookAccount {
    if(!_accountStore)
		_accountStore = [[ACAccountStore alloc] init];
	ACAccountType *facebookTypeAccount =
    [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
    NSArray *accounts = [_accountStore accountsWithAccountType:facebookTypeAccount];
    _facebookAccount = [accounts lastObject];
}

-(void) uploadVideoInFBNativeMode {
	if(!_accountStore)
		_accountStore = [[ACAccountStore alloc] init];
	ACAccountType *facebookTypeAccount =
		[_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
    [_accountStore requestAccessToAccountsWithType:facebookTypeAccount
                                           options:@{ACFacebookAppIdKey:@"445497148858001",
								ACFacebookPermissionsKey: @[@"publish_stream"], ACFacebookAudienceKey: ACFacebookAudienceOnlyMe}
                                        completion:^(BOOL granted, NSError *error) {
										if (granted) {
											NSArray *accounts = [_accountStore accountsWithAccountType:facebookTypeAccount];
											_facebookAccount = [accounts lastObject];
											[self uploadVideo];
										} else {
											NSLog(@"Error: %@", error);
											if (error.code == 6) {
												NSLog(@"%s: Error: Set facebook account in device settings",
													  __PRETTY_FUNCTION__);
											}
											[super.delegate didFailedSharingMedia:_sharedMediaData through:self
																		withError:error];
										}
									}];
}

- (void) uploadVideo {
    NSURL* videourl = [NSURL URLWithString:@"https://graph.facebook.com/me/videos"];
	NSString* filePath = _sharedMediaData.path;
	NSURL* pathURL = [[NSURL alloc] initFileURLWithPath:filePath isDirectory:NO];
    NSData* videoData = _sharedMediaData.data;
    NSDictionary* params = @{@"title": @"",
							   @"description": _sharedMediaData.fileName};
    SLRequest* request = [SLRequest requestForServiceType:SLServiceTypeFacebook
                                              requestMethod:SLRequestMethodPOST
                                                        URL:videourl
                                                 parameters:params];
    [request addMultipartData:videoData
                       withName:@"source"
                           type:@"video/mp4"
                       filename:[pathURL absoluteString]];
    request.account = _facebookAccount;
    [request performRequestWithHandler:^(NSData* responseData,
										 NSHTTPURLResponse* urlResponse,
										 NSError* error) {
        if (error) {
            NSLog(@"%s: Error %@", __FUNCTION__, error.localizedDescription);
			[super.delegate didFailedSharingMedia:_sharedMediaData through:self
										withError:error];
        } else {
			[super.delegate didFinishSharingMedia:_sharedMediaData through:self];
		}
    }];
}

@end
